﻿#region File Description
//-----------------------------------------------------------------------------
// AudioManager.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
// Edited by Petrie van Zyl
//-----------------------------------------------------------------------------
#endregion

#region Usings
using System;
using System.Collections.Generic;



using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;

#endregion

namespace PolyGameEngine.Tools
{
    public class AudioMan : GameComponent
    {
        private static AudioMan audioManager = null;

        static Random rand = new Random();

        private AudioEngine audioEngine;
        private SoundBank soundBank;
        private WaveBank waveBank;

        private static AudioCategory rollCategory;


        private AudioMan(Game game)
            : base(game)
        {
            try
            {
                audioEngine = new AudioEngine("Content\\Audio\\Polyxact.xgs");
                waveBank = new WaveBank(audioEngine, "Content\\Audio\\Wave Bank.xwb");
                soundBank = new SoundBank(audioEngine, "Content\\Audio\\Sound Bank.xsb");

                rollCategory = audioEngine.GetCategory("Roll");
            }
            catch (NoAudioHardwareException)
            {
                // silently fall back to silence
                audioEngine = null;
                waveBank = null;
                soundBank = null;
            }
        }

        public static void Initialize(Game game)
        {
            audioManager = new AudioMan(game);
            if (game != null)
                game.Components.Add(audioManager);

        }



        /// //////////////////////////////////////////////////////////////////
        /// //////////////////////////////////////////////////////////////////
        private static string introCue;
        private static string loopCue;


        public static int iLoop = 0;

        public static void PlayMusic()
        {

            int selectTrack = rand.Next(0, 3);

            switch (selectTrack)
            {
                case 0:
                    introCue = "Track1intro";
                    loopCue = "Track1loop";
                    break;
                case 1:
                    introCue = "Track2intro";
                    loopCue = "Track2loop";
                    break;
                case 2:
                    introCue = "Track3intro";
                    loopCue = "Track3loop";
                    break;
            }

            PlayMusic(introCue);
            iLoop = 1;

        }

        public static void updateLoop()
        {
            if (audioManager.musicCue.IsStopped)
            {
                PlayMusic(loopCue);
                iLoop = 0;
            }
        }

        public Cue pauseCue;
        public Cue menuCue;

        public static void menuPlay()
        {
            audioManager.menuCue.Play();
        }
        public static void menuStop()
        {
            if (audioManager.menuCue.IsPlaying)
                audioManager.menuCue.Stop(AudioStopOptions.Immediate);
        }

        public static bool getPause()
        {
            if (audioManager.pauseCue.IsPlaying)
                return true;
            else
                return false;
        }

        public static void PauseMusicOn()
        {
            audioManager.pauseCue = GetCue("Pauseloop");

            if (audioManager.musicCue != null)
            audioManager.musicCue.Pause();

            audioManager.pauseCue.Play();
        }

        public static void PauseMusicOff()
        {
            if (audioManager.musicCue != null)
                audioManager.musicCue.Resume();
            audioManager.pauseCue.Stop(AudioStopOptions.Immediate);
        }

        public Cue RollCue;

        public static void LoadSounds()
        {

            audioManager.pauseCue = GetCue("Pauseloop");
            audioManager.menuCue = GetCue("Pauseloop");

            audioManager.RollCue = GetCue("RollLoop");
            rollCategory.SetVolume(0);
            audioManager.RollCue.Play();
        }

        public static void RollUpdate(float speed)
        {
            rollCategory.SetVolume(Math.Abs(speed));
        }



        /// //////////////////////////////////////////////////////////////////
        /// //////////////////////////////////////////////////////////////////

        /// <summary>
        /// Retrieve a cue by name.
        /// </summary>
        /// <param name="cueName">The name of the cue requested.</param>
        /// <returns>The cue corresponding to the name provided.</returns>
        public static Cue GetCue(string cueName)
        {
            if (String.IsNullOrEmpty(cueName) ||
                (audioManager == null) || (audioManager.audioEngine == null) ||
                (audioManager.soundBank == null) || (audioManager.waveBank == null))
            {
                return null;
            }
            return audioManager.soundBank.GetCue(cueName);
        }

        /// <summary>
        /// Plays a cue by name.
        /// </summary>
        /// <param name="cueName">The name of the cue to play.</param>
        public static void PlayCue(string cueName)
        {
            if ((audioManager != null) && (audioManager.audioEngine != null) &&
                (audioManager.soundBank != null) && (audioManager.waveBank != null))
            {
                audioManager.soundBank.PlayCue(cueName);
            }
        }

        #region Music


        /// <summary>
        /// The cue for the music currently playing, if any.
        /// </summary>
        private Cue musicCue;


        /// <summary>
        /// Stack of music cue names, for layered music playback.
        /// </summary>
        private Stack<string> musicCueNameStack = new Stack<string>();


        /// <summary>
        /// Plays the desired music, clearing the stack of music cues.
        /// </summary>
        /// <param name="cueName">The name of the music cue to play.</param>
        public static void PlayMusic(string cueName)
        {
            // start the new music cue
            if (audioManager != null)
            {
                audioManager.musicCueNameStack.Clear();
                PushMusic(cueName);
            }
        }


        /// <summary>
        /// Plays the music for this game, adding it to the music stack.
        /// </summary>
        /// <param name="cueName">The name of the music cue to play.</param>
        public static void PushMusic(string cueName)
        {
            // start the new music cue
            if ((audioManager != null) && (audioManager.audioEngine != null) &&
                (audioManager.soundBank != null) && (audioManager.waveBank != null))
            {
                audioManager.musicCueNameStack.Push(cueName);
                if ((audioManager.musicCue == null) ||
                    (audioManager.musicCue.Name != cueName))
                {
                    if (audioManager.musicCue != null)
                    {
                        audioManager.musicCue.Stop(AudioStopOptions.AsAuthored);
                        audioManager.musicCue.Dispose();
                        audioManager.musicCue = null;
                    }
                    audioManager.musicCue = GetCue(cueName);
                    if (audioManager.musicCue != null)
                    {
                        audioManager.musicCue.Play();
                    }
                }
            }
        }


        /// <summary>
        /// Stops the current music and plays the previous music on the stack.
        /// </summary>
        public static void PopMusic()
        {
            // start the new music cue
            if ((audioManager != null) && (audioManager.audioEngine != null) &&
                (audioManager.soundBank != null) && (audioManager.waveBank != null))
            {
                string cueName = null;
                if (audioManager.musicCueNameStack.Count > 0)
                {
                    audioManager.musicCueNameStack.Pop();
                    if (audioManager.musicCueNameStack.Count > 0)
                    {
                        cueName = audioManager.musicCueNameStack.Peek();
                    }
                }
                if ((audioManager.musicCue == null) ||
                    (audioManager.musicCue.Name != cueName))
                {
                    if (audioManager.musicCue != null)
                    {
                        audioManager.musicCue.Stop(AudioStopOptions.AsAuthored);
                        audioManager.musicCue.Dispose();
                        audioManager.musicCue = null;
                    }
                    if (!String.IsNullOrEmpty(cueName))
                    {
                        audioManager.musicCue = GetCue(cueName);
                        if (audioManager.musicCue != null)
                        {
                            audioManager.musicCue.Play();
                        }
                    }
                }
            }
        }


        /// <summary>
        /// Stop music playback, clearing the cue.
        /// </summary>
        public static void StopMusic()
        {
            if (audioManager != null)
            {
                audioManager.musicCueNameStack.Clear();
                if (audioManager.musicCue != null)
                {
                    audioManager.musicCue.Stop(AudioStopOptions.AsAuthored);
                    audioManager.musicCue.Dispose();
                    audioManager.musicCue = null;
                }
            }
        }


        #endregion


        #region Updating Methods


        /// <summary>
        /// Update the audio manager, particularly the engine.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // update the audio engine
            if (audioEngine != null)
            {
                audioEngine.Update();
            }

            //if ((musicCue != null) && musicCue.IsStopped)
            //{
            //    AudioManager.PopMusic();
            //}

            base.Update(gameTime);
        }

        #endregion

        /// <summary>
        /// Clean up the component when it is disposing.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            try
            {
                if (disposing)
                {
                    StopMusic();
                    if (soundBank != null)
                    {
                        soundBank.Dispose();
                        soundBank = null;
                    }
                    if (waveBank != null)
                    {
                        waveBank.Dispose();
                        waveBank = null;
                    }
                    if (audioEngine != null)
                    {
                        audioEngine.Dispose();
                        audioEngine = null;
                    }
                }
            }
            finally
            {
                base.Dispose(disposing);
            }
        }


    }
}


/*
   //////////INITIALIZE///////////////////

            AudioMan.Initialize(this);
            AudioMan.setRoll();
 * 
            AudioMan.PlayMusic();
  
 * ////////////////////////////////////


  //////////UPDATE///////////////////
 * 
              if (AudioMan.iLoop == 1)
                AudioMan.updateLoop();

            if (InputMan.OnPress(Keys.Q))
            {
                if (AudioMan.getPause())
                    AudioMan.PauseMusicOff();
                else
                    AudioMan.PauseMusicOn();
            }
 * 
 * ////////////////////////////////////
 * 
 * 
  //////////Circleuunt///////////////////
 * 
 *         float MaxAngularVelocity = 20;

        public override void Update(GameTime gameTime)
        {
            if (canJump)
              AudioMan.RollUpdate(body.AngularVelocity);
            else
              AudioMan.RollUpdate(0);
            
            base.Update(gameTime);
        }
 * ////////////////////////////////////
 */